第十七章 AT32F403A基于V2库 定时器输入捕获 | 您所在的位置:网站首页 › sites v2资料 › 第十七章 AT32F403A基于V2库 定时器输入捕获 |
目录 概述 硬件 输入捕获 软件 初始化 初始化代码
中断服务函数 测试 最后 概述本文主要是使用AT32F403A开发板,基于V2库实现定时器输入捕获功能。 串口工具使用的Atlink-ez自带的串口功能。 工程建立、调试工具配置在前面章节有详细介绍。 硬件 硬件方面使用的是参考官方AT32F437 SURF板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。 如下图是开发板pcb图,以及硬件资源。(左边上角的就是atlink-ez,用usb线接到pc即可): 如下是实物图: 本章是tmr的输入捕获的功能,使用的是TMR3使用的通道1(PA6),输入直接接到PA6的排针上即可。 输入捕获通用定时器和高级定时器都有输入捕获的功能,每个通道是相互独立的,在输入模式下,在通道有输入后,通道数据寄存器会记录下此刻定时器的计数值,并触发中断、dma等。输入功能的使用原理就是根据两次触发的计数值的差算出输入的信号的周期。 本章TMR3使用的通道1(PA6),先要设置gpio为输入模式。 使能定时器的时钟,然后设置预分频、分频和重载值,设置计数方式,设置通道的输入参数,使能通道比较中断,编写中断服务函数。 typedef struct { tmr_channel_select_type input_channel_select; /*!< tmr input channel select */ tmr_input_polarity_type input_polarity_select; /*!< tmr input polarity select */ tmr_input_direction_mapped_type input_mapped_select; /*!< tmr channel mapped direct or indirect */ uint8_t input_filter_value; /*!< tmr channel filter value */ } tmr_input_config_type; input_channel_select:输入的通道 input_polarity_select:触发方式 input_mapped_select:映射模式 input_filter_value:输入滤波器值 设置通道1输入,上升沿触发,直接映射模式,无滤波,输入1分频。 中断服务函数中,是通过对两次上升沿之间的计数差计算出一个周期的时间,所以需要注意输入的周期不能太大。TMR3是16bit的定时器,重载值最大只能设置为65536,当TMR3的计数时钟为240M的时候,那么周期就是65536/240 us,当输入的周期大于定时器的周期的时候,那么定时器已经在重新从计数,实际的时间比我们捕获到的时间就可能是多个定时器的周期之差了。 想要高精度的捕获并且输入的周期长的,那么可以使用定时器的溢出中断、增加标志以及计数来计算输入的周期。 初始化代码 /** *TMR3 输出输入捕获初始化函数 *预分频1,重载值0xffff *定时器计数时钟240M, *周期:(65536/240)us=273us, * * */ void input_tmr3_init(void) { gpio_init_type gpio_init_struct; tmr_input_config_type tmr_input_config_struct; crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE); //开启tmr3时钟 crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); //开启gpioa时钟 gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_pins = GPIO_PINS_6 ; //PA6 gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; //推挽(输入模式,此参数无效) gpio_init_struct.gpio_pull = GPIO_PULL_NONE; //无上下拉 gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; //输入模式 gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOA, &gpio_init_struct); tmr_base_init(TMR3, 0xffff, 0); //设置TMR3的预分频为1=0+1;重载值480=479+1;(参数要减去1) tmr_cnt_dir_set(TMR3, TMR_COUNT_UP); //设置为向上计数方式 /* configure tmr3 channel1 to get clock signal */ tmr_input_config_struct.input_channel_select = TMR_SELECT_CHANNEL_1; //通道1 tmr_input_config_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT; //直接映射 tmr_input_config_struct.input_polarity_select = TMR_INPUT_RISING_EDGE; //上升沿 tmr_input_config_struct.input_filter_value=0; //不滤波 tmr_input_channel_init(TMR3, &tmr_input_config_struct, TMR_CHANNEL_INPUT_DIV_1); //输入1分频 tmr_interrupt_enable(TMR3, TMR_C1_INT, TRUE); //使能TMR3通道1中断 nvic_irq_enable(TMR3_GLOBAL_IRQn, 0, 0); //使能tmr3中断 /* enable tmr3 */ tmr_counter_enable(TMR3, TRUE); //使能定时器 } 中断服务函数 __IO uint32_t tmr3freq = 0; __IO uint32_t sys_counter = 0; __IO uint16_t capturenumber = 0; __IO uint16_t ic3readvalue1 = 0, ic3readvalue2 = 0; __IO uint32_t capture = 0; /** * TMR3中断服务函数 * * */ void TMR3_GLOBAL_IRQHandler(void) { if(tmr_flag_get(TMR3, TMR_C1_FLAG) != RESET) //通道1中断 { tmr_flag_clear(TMR3, TMR_C1_FLAG); //清除通道1中断 if(capturenumber == 0) //第一次捕获到高电平 { /* get the Input Capture value */ ic3readvalue1 = tmr_channel_value_get(TMR3, TMR_SELECT_CHANNEL_1); //把通道1的数值保存起来 capturenumber = 1; } else if(capturenumber == 1) //第二次捕获到高电平 { /* get the Input Capture value */ ic3readvalue2 = tmr_channel_value_get(TMR3, TMR_SELECT_CHANNEL_1); //把通道1的数值保存起来 /* capture computation */ if(ic3readvalue2 > ic3readvalue1) //判定是否有超过0xffff,这里就是限制了输入的最低频率。 { capture = (ic3readvalue2 - ic3readvalue1); //两个高电平之间的计数差,也就是1个周期的时间 } else { capture = ((0xFFFF - ic3readvalue1) + ic3readvalue2); //两个高电平之间的计数差,也就是1个周期的时间 } /* frequency computation */ tmr3freq = (uint32_t) get_rcc_clock.sclk_freq / capture; //计算出输入的频率。 capturenumber = 0; } } } 测试测试代码 使用上一章的pwm输出,使用TMR1的ch1(PA8)输出1M的频率,短接到PA6.然后每1000ms输出一次log。 测试结果 捕获得到的频率和我们实际输入的频率一致。 有问题的可以加QQ群技术交流,同时相关代码上传到QQ群中。 |
CopyRight 2018-2019 实验室设备网 版权所有 |